﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com/EmlenMud
using System;
using System.ComponentModel;
using BrainTechLLC;
using System.Drawing;
using System.IO;
using System.Threading;
using BrainTechLLC.WPF;
using System.Diagnostics;
using System.Drawing.Imaging;
using BrainTechLLC.BaseLibrary;
using System.Windows.Media;
using BrainTechLLC.ImageOperatorsNonAForgeDependent;

namespace SimpleFileDataAndViewModels
{
    public class HasBytes : BaseNotifyPropertyChangedUI, INotifyPropertyChanged, IObjectLock, IContainsBytes
    {
        protected object _lockObject = new object();
        object IObjectLock.LockObject { get { return _lockObject; } }
        public static ICoreDataProvider DefaultDataProvider;
        protected string _fileName;
        public ICoreDataProvider _DataProvider;        
        public byte[] _Bytes;

        public byte[] Bytes
        {
            get
            {
                return _Bytes;
            }
            set
            {
                if (_Bytes != value)
                {
                    _Bytes = value;
                    OnPropertyChanged("Bytes");
                }
            }
        }        

        public ICoreDataProvider DataProvider
        {
            get
            {
                if (_DataProvider == null)
                {
                    _DataProvider = DefaultDataProvider;
                }
                return _DataProvider;
            }
            set
            {
                if (_DataProvider != value)
                {
                    _DataProvider = value;
                }
            }
        }
        
        public string FileName
        {
            get { return _fileName; }
            set
            {
                if (_fileName != value)
                {
                    _fileName = value;
                    OnPropertyChanged("FileName");
                }
            }
        }

        public byte[] Load()
        {
            int fileSize = 0;
            int tries = 0;
            byte[] bytes = null;
            bool noGood = true;

            Timing.BeginTiming();

            while (noGood)
            {
                FileLocking.GetFileLock(_fileName);

                try
                {
                    EnterMonitor(_lockObject, 10);

                    try
                    {
                        bytes = DataProvider.ReadAllImageBytes(_fileName);
                        noGood = false;
                    }
                    catch (FileNotFoundException)
                    {
                        return null;
                    }
                    catch (IOException)
                    {
                        if (tries++ > 5)
                        {
                            throw;
                        }
                        else
                        {
                            Monitor.Exit(_lockObject);
                            Thread.Sleep(300);
                            Console.WriteLine("SHOULD NOT HAPPEN");
                            EnterMonitor(_lockObject, 20);
                        }
                    }
                    finally
                    {
                        Monitor.Exit(_lockObject);
                    }
                }
                finally
                {
                    FileLocking.ReleaseFileLock(_fileName);

                    if (bytes != null)
                    {
                        fileSize = bytes.Length;
                        Timing.EndTiming((d) => AllStats.GetInstance().AddTime("AverageLoadTime", ((double)fileSize * 1024D) / (double)d));
                    }
                    else
                    {
                        Timing.EndTiming((d) => { });
                    }
                }
            }

            //Console.WriteLine(string.Format("Loaded {0}, {1} KB", _fileName, fileSize / 1024));
            Debug.WriteLine(string.Format("Loaded {0}, {1} KB", _fileName, fileSize / 1024));
            return bytes;
        }
        
        public virtual void ClearAll()
        {
            Bytes = null;
        }
    }
}
